package sesi.ejava.stream;

/**
 * This singleton class is used by the control activities to send the control
 * information through the bluetooth connection. It contains the internal class
 * ControlData to provide an easy way to organize the data to be send.
 * 
 * @see ControlData
 * 
 * @author Cesar Fuguet
 * 
 */
public class ControlOutputStream {
	private BluetoothManagerService bluetoothManagerService;
	private static ControlOutputStream instance = null;

	private ControlOutputStream() {
		bluetoothManagerService = BluetoothManagerService.getInstance();
		bluetoothManagerService.setHandler(null);
		bluetoothManagerService.setContext(null);
	}

	/**
	 * This class is a singleton. The only way to get the singleton instance is
	 * using this function.
	 * 
	 * @return singleton instance
	 */
	public static synchronized ControlOutputStream getInstance() {
		if (instance == null) {
			instance = new ControlOutputStream();
		}

		return instance;
	}

	/**
	 * Send the control data to the server device
	 * 
	 * @param data
	 *            ControlData object to be send
	 * 
	 * @return -1 if the BluetoothManagerService is not connected and 0
	 *         otherwise
	 */
	public int sendData(ControlData data) {
		if (!bluetoothManagerService.isConnected()) {
			return -1;
		}

		byte[] byteStream = new byte[6];

		byte firstByte = 0;
		firstByte += (data.isPositionLights()) ? 1 : 0;
		firstByte += (data.isDippedHeadlights()) ? 2 : 0;
		firstByte += (data.isMainBeam()) ? 4 : 0;
		firstByte += (data.isRearFogLamp()) ? 8 : 0;
		firstByte += (data.isFrontFogLamp()) ? 16 : 0;
		firstByte += (data.isWarning()) ? 32 : 0;
		firstByte += (data.isRearDefrost()) ? 64 : 0;
		firstByte += (data.isAirEntrance()) ? 128 : 0;

		byte secondByte = 0;
		secondByte += (data.isCarLock()) ? 1 : 0;
		secondByte += (data.isFrontRightWindow()) ? 2 : 0;
		secondByte += (data.isFrontLeftWindow()) ? 4 : 0;
		secondByte += (data.isRearLeftWindow()) ? 8 : 0;
		secondByte += (data.isRearRightWindow() ? 16 : 0);
		secondByte += (data.isDashboardLight()) ? 32 : 0;
		secondByte += (data.isCockpitLight()) ? 64 : 0;

		byteStream[0] = firstByte;
		byteStream[1] = secondByte;
		byteStream[2] = (byte) (data.temperature & 0x00FF);
		byteStream[3] = (byte) (data.temperature & 0xFF00);
		byteStream[4] = data.fanSpeed;
		byteStream[5] = data.fanZone;

		bluetoothManagerService.write(byteStream);

		return 0;
	}

	/**
	 * This internal class is used to encapsulate all the control data
	 * informations
	 */
	public class ControlData {
		private boolean positionLights; // Feux de position
		private boolean dippedHeadlights; // Feux de croisement
		private boolean mainBeam; // Feux de route
		private boolean rearFogLamp; // Feux de brouillard arriere
		private boolean frontFogLamp; // Feux de brouillard avant
		private boolean warning;
		private short temperature; // Température de la clim
		private byte fanSpeed; // Vitesse de la ventilation
		private byte fanZone; // Zone de la clim
		private boolean rearDefrost; // Dégivrage arrière
		private boolean airEntrance; // Entrée d'air
		private boolean carLock; // Fermature de la voiture
		private boolean frontRightWindow;
		private boolean frontLeftWindow;
		private boolean rearLeftWindow;
		private boolean rearRightWindow;
		private boolean dashboardLight;
		private boolean cockpitLight;

		/**
		 * @return Position Lights (Feux de position)
		 */
		public boolean isPositionLights() {
			return positionLights;
		}

		public void setPositionLights(boolean positionLights) {
			this.positionLights = positionLights;
		}

		/**
		 * @return Dipped Headlights (Feux de croisement)
		 */
		public boolean isDippedHeadlights() {
			return dippedHeadlights;
		}

		public void setDippedHeadlights(boolean dippedHeadlights) {
			this.dippedHeadlights = dippedHeadlights;
		}

		/**
		 * @return Main Beam (Feux de route)
		 */
		public boolean isMainBeam() {
			return mainBeam;
		}

		public void setMainBeam(boolean mainBeam) {
			this.mainBeam = mainBeam;
		}

		/**
		 * @return Read Fog Lamp (Feux de brouillard arriere)
		 */
		public boolean isRearFogLamp() {
			return rearFogLamp;
		}

		public void setRearFogLamp(boolean rearFogLamp) {
			this.rearFogLamp = rearFogLamp;
		}

		/**
		 * @return Front Fog Lamp (Feux de brouillard avant)
		 */
		public boolean isFrontFogLamp() {
			return frontFogLamp;
		}

		public void setFrontFogLamp(boolean frontFogLamp) {
			this.frontFogLamp = frontFogLamp;
		}

		/**
		 * @return Warning
		 */
		public boolean isWarning() {
			return warning;
		}

		public void setWarning(boolean warning) {
			this.warning = warning;
		}

		/**
		 * @return Temperature
		 */
		public short getTemperature() {
			return temperature;
		}

		public void setTemperature(short temperature) {
			this.temperature = temperature;
		}

		/**
		 * @return Fan Speed (Vitesse de la ventilation)
		 */
		public byte getFanSpeed() {
			return fanSpeed;
		}

		public void setFanSpeed(byte fanSpeed) {
			this.fanSpeed = fanSpeed;
		}

		/**
		 * @return Fan Zone (Zone de la ventilation)
		 */
		public byte getFanZone() {
			return fanZone;
		}

		public void setFanZone(byte fanZone) {
			this.fanZone = fanZone;
		}

		/**
		 * @return Read defrost (Dégivrage arrière)
		 */
		public boolean isRearDefrost() {
			return rearDefrost;
		}

		public void setRearDefrost(boolean rearDefrost) {
			this.rearDefrost = rearDefrost;
		}

		/**
		 * @return Air Entrance (Entree d'air)
		 */
		public boolean isAirEntrance() {
			return airEntrance;
		}

		public void setAirEntrance(boolean airEntrance) {
			this.airEntrance = airEntrance;
		}

		/**
		 * @return Car lock (fermature de la voiture)
		 */
		public boolean isCarLock() {
			return carLock;
		}

		public void setCarLock(boolean carLock) {
			this.carLock = carLock;
		}

		public boolean isFrontRightWindow() {
			return frontRightWindow;
		}

		public void setFrontRightWindow(boolean frontRightWindow) {
			this.frontRightWindow = frontRightWindow;
		}

		public boolean isFrontLeftWindow() {
			return frontLeftWindow;
		}

		public void setFrontLeftWindow(boolean frontLeftWindow) {
			this.frontLeftWindow = frontLeftWindow;
		}

		public boolean isRearLeftWindow() {
			return rearLeftWindow;
		}

		public void setRearLeftWindow(boolean rearLeftWindow) {
			this.rearLeftWindow = rearLeftWindow;
		}

		public boolean isRearRightWindow() {
			return rearRightWindow;
		}

		public void setRearRightWindow(boolean rearRightWindow) {
			this.rearRightWindow = rearRightWindow;
		}

		public boolean isDashboardLight() {
			return dashboardLight;
		}

		public void setDashboardLight(boolean dashboardLight) {
			this.dashboardLight = dashboardLight;
		}

		public boolean isCockpitLight() {
			return cockpitLight;
		}

		public void setCockpitLight(boolean cockpitLight) {
			this.cockpitLight = cockpitLight;
		}
	}
}
